in this video we're going to make a hook
shot mechanic in unity when we press a
button we fire the hook shot and when it
connects to an object it starts pulling
the player towards it by jumping wrong
being pulled we keep our momentum which
lets us have some really cool movement
let's begin
[Music]
hello and welcome I'm your code monkey
and this channel is all about helping
you learn how to make your own games
with in-depth tutorials made by a
professional indie game developer so if
you find the video helpful consider
subscribing okay so first of all the
origin for this mechanic was from the
FPS game that I made recently I took
unities FPS micro game base and built a
bunch of mechanics on top the hookshot
has been the most requested one so here
I won't cover exactly how it works if
you haven't seen that video or played
through the game then go check it out
it's a very short game that you can play
fully in your browser and it has some
really interesting mechanics I've also
done a showcase video where I go through
the game and talk about all the elements
I build so check that out as well now
here this is what we want to create I
have my player character in a very
normal level and I can move and walk
around now I can look at a point on that
wall and by pressing a key there you go
the hookshot goes flying it hooks onto
the wall and it pulls me towards it then
if I wait until I reach the destination
the hookshot simply stops and I start
falling down
however if I'm mid-air being pulled and
I press the jump button there you go the
jump continues I contain with my
momentum and it had some height so I can
go in there jump above it and there you
go just like that I can combine it with
almost everything and move everywhere so
with this I can really quickly get
around level and get anywhere in like
for example on this hidden area right up
here yep there you go nice this is a
really great fun mechanic to play around
with and really makes your first-person
shooter and a lot more fun to play
alright so this circle let's get to it
okay so here's our starting scene I'm
standing in a basic world with a very
basic FPS controller so I can move and I
can look around I can jump and the
character is affected by gravity over
here in the editor you can see the setup
for the character it has a standard
character controller as well as a player
character controller inside the game
object we have our simple camera so
let's check out the player character
controller script okay here it is and
it's very small and very simple we grab
the character controller as well as the
camera we also make sure to lock the
mouse in the center then we just have
two functions one which were happy mouse
input and simply rotates the transform
and the
another function to handle our very
simple movement so you grab the input
create a velocity vector then we test if
we should jump we apply gravity to our
character velocity and finally we move
the character controller so here is our
very simple character controller all
right now our goal here is to make a
hook-shot mechanic so we want to be able
to look at a certain position then press
a button as soon as we do a hook-shot
won't be thrown from the player towards
that position and when it connects it
should pull the player towards it okay
so here in our player controller let's
go all the way down here and make a
private boy call it handle hook shot
start so we're going to call this on
update so up here we handled all the
movement and now the hook shot
now in here let's search for a simple
key input so let's simply do a input get
key down of let's say when we press the
e so when we press a key let's test what
we're looking at so the way we do that
is by making a simple physics dot
raycast so here it takes an origin and a
direction so we go into the player
camera grab the transform position then
for the direction we use the player
camera transform and we use the forward
vector since the camera is already I'm
looking at the mouse position so just
like that we have our origin and our
direction and now we can use the final
parameter to get our ray cast hit and
this returns a boolean if it does hit
something okay just like that so here we
can use the raycast hit and use the
point which contains the exact point
where the rake has hit the collider all
right so let's see how we can test this
now we can go up here to add a field for
a simple transform so let's add another
serialize field or a private transform
let's call this the debug hit point
transform okay now we go into the editor
here's our script with our field so
let's create a new cue and let's apply
this nice material so it's nice and
green okay okay let's write the
reference for the
cube in there there it is you know here
when we hit something
let's simply take our debug transform
and set the position to be our break
asset dot point
okay that should do it so we do a recast
towards where we're looking at and if we
hit something we're going to place our
object exactly where we hit let's see
okay here we are and there's the nice
cube now let's look in there Pressey any
of there you go the cube gets placed
exactly where I pressed so there you go
just like that I can look anywhere and
it's correctly doing a recast and
hitting the correct position all right
awesome
now back in our code when we have the
correct position we want to move towards
it so let's go all the way up here to
make this a simple state machine so
first we define an enum for our state's
and we're going to start off just with a
normal state so we also have a variable
- home our current state and on awake we
start off as normal
okay then on the update we can do a
simple switch on our state okay if we
our state normal we do the same we were
doing previously okay and now we can
make another state for when the player
is being pulled by the hookshot
and now we do a different thing on our
case this state okay so let's make the
function that we're going to run in here
so we have a function to handle our
hookshot movement and we simply call it
on our update in here okay and when we
start our hookshot
let's modify our state to be our new
hookshot flying state all right so we
have implemented a very basic state
machine now here in our hookshot
movement we're going to move the
character controller so pretty much the
same as this so in order to do it we
need a direction in order to calculate
the direction we need a position so
let's store our hookshot position so we
store a vector3 for the hookshot
position and down here when we hit
something well it said the hookshot
position to be our rake asset dot point
okay so now we know exactly where we
want to hook into so now on the hookshot
movement we can calculate a vector3 for
the hookshot direction and direction is
simply the target position - our current
position and normalize that vector okay
so we have the hookshot direction as
well as the position and now we can
simply move it towards our hookshot
direction just like that and it's also
quite basic pop shot speed okay so here
it is very simple as soon as we press on
the e we're going to do a recast if the
raycast hits something then we're going
to set our hook shot position vector and
we're going to modify our state then
when we have this state we're going to
call this function and in this function
we're going to calculate the direction
towards our hook shot position and we're
simply going to move the character
towards it at a certain speed
let's test okay here we are let's click
in there and press E and there you go it
correctly set the hook shot position and
it's moving towards it right great but
you can already see plenty of issues
first of all there's no camera movement
I'm moving the mouse but the camera
isn't loading anywhere then we also have
an issue with a speed being extremely
slow and finally when we reach our hook
shot position yep we are stuck and we no
longer fall down that's because we did
not reset our state so let's solve all
of those issues
first of all dealing with the camera
looking is extremely simple we already
have a separate function just the hand
on the character and look and only need
to do is also call this well skier
flying there it is let's see okay here
we are on with NER press E and there you
go now I'm being pulled towards it and I
can say look around okay so far so good
now let's see always resetting our state
so we go all the way down here where we
are handling our hookshot movement and
after removing let's do a very simple
distance check so we do if vector3
distance the distance between the
current transformed our position and the
hookshot position if that distance is
under a certain amount
if it isn't there a certain amount and
we have reached our hookshot position so
it's in here that we want to reset back
to our normal state so we simply set the
state equals our state normal okay
that's pretty much it let's see so here
we are on let's look in there press e
and there you go I'm being pulled toward
extremely slowly so let's wait until we
get there
okay we're almost there and when I reach
the hookshot position yep there you go I
phone down according to the gravity
exactly as intended all right awesome so
now the remaining issue is with the
speed so when I press it's very slow we
want to speed it up and be faster at the
beginning and then slower at the end so
here in our hookshot movement let's play
around with our speed and we will make
it faster in that slower is by having
the movement be based on the distance so
we set the hookshot speed to be a
distance between our transform position
and the hookshot position okay so just
like this the speed will be faster the
further away we are and then let's also
have a secondary speed multiplier just
in case our actual distance is too slow
of a speed so then in here we use the
hookshot speed multiplied by the
multiplier and by Delta time okay so
just like this we should be able to see
our speed faster and then slower let's
see so here we are let's look in there
proceed and there you go he pulls really
fast and then really slow and then he
falls out so click go really fast really
slow and slow down right great so this
is working however we have an issue with
the speed being way too low as we reach
very close towards the end we should
keep a minimum velocity at all times so
it's very simple to do that here on our
speed we can simply define a minimum and
a maximum
okay we have our minimum and maximum and
then we simply do a math F dot clamp and
we're going to clamp this value between
our minimum and our maximum so no matter
how close we are we are never going to
move slower than this one and no matter
how far we are it's never going to be
faster than this one let's test so here
I am looking there press E and there yo
gets foamed and yep there you go the
speed is no longer super slow at the
bottom and goes just like that so now we
can play around with the multiplier and
with the various values okay here it is
press e and there you go gets one really
fast and then slows down but it always
remains quite a nice speed yep just like
that all right great now one other issue
we have is regarding our gravity so
right now the gravity is not resetting
so as I hookshot
if I don't let it touch the floor there
you go the gravity becomes more and more
intense so just like that I almost fall
down instantly so let's go into the code
now the reason why that is happening is
because of how we decide to handle our
grouting so we have a character velocity
Y that we are pushing down on every
frame and it only gets reset when the
character is ground so if the character
never actually gets grounded then the
gravity down force just keeps increasing
and increasing so we can fix this very
simply by resetting our gravity velocity
Y force whenever we go back into our
normal state so we can simply do a
private coin called reset gravity effect
and you simply do what we were doing
here so we set the velocity right back
into zero and then down here when we go
back into our normal state we reset our
gravity effect okay let's test so here I
am and I can hook shot and hook shot
again and again and you have to go the
gravity is now resetting every time I
hook shot so I can keep jumping up and
down and never touch the floor all right
awesome
so I can hook shot anywhere and the
effect is already starting to look quite
nice however right now we have no
control in me there so we get pulled
towards it and we can only go back into
moving as soon as we reach the position
so let's first add a simple cancel so we
can cancel the hookshot whilst moving in
midair so when we are handling our
hookshot movement
let's test for the
input that we use to start our hook shot
so here and put this into a separate
function okay on this one we just
returned our function and just like that
we use it in here okay so this way if we
want to change our input we just have to
modify this function so then in here we
first if we press that same input so if
you press the same input once we're
moving one to cancel the hookshot in
order to cancel it it's extremely simple
all we have to do is pretty much just
this we reset into our normal state that
should do it let's test okay here I am
and let's hook shot in there and stop in
the middle any of there you go he stops
immediately and starts falling down so I
can now cancel them anywhere I want so
cancel cancel and yep just like that
okay so cancel is great but now let's
see on with the more interesting action
of jumping well cinema there so back in
our code let's also make another
function for testing the input on the
jump since in here we're using the key
directly okay so we test the jump on the
space and we can also use it in here
instead of hard-coding our key okay and
on our handle hookshot movement we test
if we hit space lost in midair so if we
jump once the hookshot is active then we
want to keep our hookshot momentum and
add a nice jump onto it so before we can
handle this we need to first handle our
character velocity momentum so we go all
the way up here next to our camera
velocity we define a vector3
call it our character velocity momentum
and then on our handle movement before
we move our character let's apply our
character momentum we simply increase
the character velocity by our momentum
okay just like that and then afterwards
we want to dampen the momentum
okay so here we have some nice momentum
being dampened so we tested magnitude is
more than zero if so then we define a
drag value and we simply reduce our
momentum by the drive value by
time.deltatime and when it's small
enough we simply set it to zero some
like this we are applying our momentum
and then constantly reducing it so down
here now when we press jump and we
cancel our hookshot we can simply set
the character velocity momentum to be
our current hookshot Direction
multiplied by the current Oakshott speed
and then multiplied by a little extra
and after we set the momentum we cancel
and go back into our normal state all
right did she do it let's test okay so
lets hook shot and then stop so hook
shot press jump and there you go he
jumps and he goes once in midair so just
like that go jump and he stops but he
keeps up with its momentum so I go there
I jump and there we go he keeps it like
that all right
great so it's starting to feel really
nice now since we were pressing jump
let's add a bit of a vertical movement
as well so in order to add our jump it's
extremely simple over here we have our
character velocity momentum based on the
hookshot direction and then we need to
do is apply this and then we simply and
a vector3 dot up multiplied by a certain
jump speed alright that's pretty much it
let's see so here I am go in there press
space and here you go now I can nicely
and jump on top of that and there you go
I can play around and I can already move
almost everywhere so here we have our
nice hook shot looking better and better
right awesome now so far our hook shot
has been instant so the second that I
press the button I get fall towards it
so let's first make a visual that
travels towards the hook shot position
and only when it connects do we get
pumped so the way we're going to do that
is extremely simple here in the editor
let's make a new cube here is the cube
let's make it a bit darker okay and now
let's put it as a child of the player
put it on zero zero zero and let's make
it thinner on the X and on the Y and
leave the set okay and now the way we're
going to do this is we're going to
increase the set scale until it reaches
the position however just like this it's
not going to work since when we scale
we're scaling from the middle instead of
from the edge so the way we do that is
we make a new game object comment our
hookshot make the cube h out of it
and now we just need to shift it forward
by half of its size so by 0.5 on the set
and now we have the hookshot and we can
modify this game about set and there we
go it now increases straight from there
alright so now let's go to the code and
first of all let's go all the way up
here at a field for our hookshot
transform and let's drag the reference
there's a reference just drag the
hookshot transfer okay
and now back in our states let's add a
new state we're going to call this the
hookshot
thrown so we have an extra state and on
our update let's handle another case for
the hookshot thrown and then down here
when we have our hook shot start instead
of going straight into the flowing let's
go into the thrown state and then we're
going to make a function call it handle
hook shot throw and this is the function
that we call whilst we're in our thrown
state so we just like that and I once in
this state it's extremely simple we just
take our hookshot transform and we can
look at and here we can pass in our
target position so that's going to be
our cookshop position so we can look at
that position and then we want to scale
towards it
so let's go up here to define a float
for our hook shot sighs okay we have our
hook shot sighs and down here when we
modify our state let's set the size back
into zero and then on the hookshot throw
we simply go and increase the size by a
certain hook shot throw speed
then we apply this size into our
transform okay so we have the size
constantly increasing and updating the
transform and now we need our end
condition so for that we do a simple
distance check so if the hookshot size
is bigger than the distance towards our
hookshot position then we have
essentially reached it with our hoja so
when we do we simply go into the next
state
okay so let's pretty much it now all we
need to do is call this function on our
talk-show our own state and when you do
let's also handle the unlock and the
movement okay let's test okay here we
are
and now the first issue that we can
already see is that the hookshot is
currently visible whereas it should be
invisible but we'll fix that later but
we can look and we can look in there and
press the E and there you go the
hookshot starts being thrown and there
it goes very slowly and I can still look
around I can move and when it finally
connects with our hookshot position
there you go almost there almost there
and yep just like that Connect and
finally yep there you go I get pull
alright so the speed is obviously very
bad and this should be hidden but let's
start those things so first in dealing
with the visibility let's try to make
our awake we go into the transform we
set the game object active to false and
then when we start our hook shot
when the hookshot gets thrown let's set
it to active to true and when we cancel
it let's set it back into false now here
we can already see some very nasty code
duplication so let's fix this while
we're at it
okay so just like this our cup looks
better and now let's see on with the
speed of our hook shot being thrown here
it is we have a very simple speed and
now here we have two options we can put
a static speed or we can do the same
thing with it with our hook shot
movement making it dependent on the
distance in this case let's simply make
it just static since it's a very quick
effect so we just make this quite a bit
faster and let's try okay here where I'm
looking there press E and there you go
there goes the hook shot sound a bit too
slow but yep it's going much faster when
it connects it goes and we can already
see another issue which is after it
connects and it starts being thrown and
there you go it no longer rotates
towards the correct position so it's
sort of those issues first word speed
let's increase it quite a bit more then
when we start there's also a frame where
we can actually see it so here when he
set it to active to true oh it's all set
the local scale to zero so that is very
small okay and finally we want to look
at the hookshot position whilst we're
handling our hook shaft movement okay
that should fix all of our issues let's
see so here we are in first of all it
starts off hidden so far so good now
looking there press E and there you go
there goes the hook shot and gets pulled
towards it and it still rotates looking
at it as it's going like that okay so
now let's make it quite a bit faster
okay so here we are and let's test in
yep there we go the speed is now much
faster and as I'm being a hook shot
there you go
it always points towards the hookshot
position just like that and I phoned out
and I can come back and there you go and
I can also move while some hook shouting
so hook shot and I can still move whilst
it's being thrown all right so our
effect is starting to look very very
nice now let's add a couple more things
first of all let's change the camera fov
while flying to really give the illusion
of speed here the camera already has a
very simple script attached onto it here
it is extremely simple extremely small
we just have a target fov and occurring
FOV and on update we simply lower power
current fov towards the target and then
we have a function that we can set our
camera FOV so let's use this first we
need a reference to our camera fov
script
so you grab our component okay and now
let's also define some constants for our
two types of FOV okay so normal we have
60 film to view and on hook shot let's
put it at 100 and now we simply use this
so we grab our camera movie and down
here on our hook shot
okay so first was throwing okay and then
only when we actually grab it then we go
into camera fov and we set the camera
fov and let's use the hook shot fov and
then when we cancel so here on our stop
hook shot function we simply reset it
into the normal ethylene alright let you
do it let's test okay here on with soap
shot in there any of their yo you can
see the hook shot changes the fov does
giving a very nice illusion of speed all
right so it's looking quite nice now one
more thing let's add a particle system
so here I have a particle system that
I've set up it just has some nice trails
so we're going to enable this once the
player is flying so here in the code
let's grab our particle system
so you grabbed the particle system
reference and then when we start our
hook shot at the same place as we modify
our fov we simply call this on play and
when we stop we simply call stop okay
that's it very simple let's test okay so
here I am
hook shot in there and there you go the
fov changes and we have the nice
particles to really sell the illusion of
speed so I can go jump jump and yep just
like that I can go anywhere I can fall
off the mouse and using the jump I can
try it yep and I made it in and back in
here and playing around alright so here
we have our very cool hook shot
and here on the left side I have a nice
special hidden area in there and now we
can try to hook shot and try to get up
there so hook shot and jump hook shot
and jump hook shot and jump and there
you go I managed to make it all the way
up here so just like this we have a
really cool mechanic to play around with
and it feels really great we can hook
shot we can jump we have all the effects
to make it work awesome and it works
great all right awesome
now you could expand upon this design
and make it so that the hook shot only
connects to certain areas rather than
every single surface you could also add
a maximum distance so you couldn't hook
shot on to infinity and you could also
add some gravity once being hook shot
and it would essentially turn the hook
shot into a rope mechanic so using this
as a base you can get really creative
and make something that perfectly suits
your game and again if you haven't
played it yet then go check out the game
I made using the FPS micro game as a
base which uses this mechanic it's a
really quick game that you can play in
our browser and it's really fun and
combines this mechanic with enemies and
shooting watched showcase video where I
talk more about how I made that game and
all the elements that go into it I'm
currently working on videos covering the
shield shader effect as well as the key
door system so if you're watching this
in the future go check out those links
in the description as always you can
download the project files in a tony's
from unity cosmic
subscribe to the channel for more unity
deterrents post any questions you have
in the comments and I'll see you next
time
[Music]